import React, { useEffect, useRef, useState } from "react"
import { Attachments, Bubble, Prompts, Sender, useXAgent, useXChat, Welcome } from "@ant-design/x"
import {
  ReloadOutlined,
  CopyOutlined,
  LikeOutlined,
  DislikeOutlined,
  ShareAltOutlined,
  EllipsisOutlined,
  CloudUploadOutlined,
  PaperClipOutlined
} from "@ant-design/icons"
import { Button, Spin, Space, Flex, message } from "antd"
import logo from "@/assets/images/dog.svg"
import { HOT_TOPICS, DESIGN_GUIDE, SENDER_PROMPTS } from "@/config/mock"
import useChatStore from "@/stores/chat"
import "./index.scss"
import type { BubbleDataType } from "@ant-design/x/es/bubble/BubbleList"
import type { GetProp } from "antd"

/**
 * AI 对话
 */
const ChatPage: React.FC = () => {
  const { curConversation } = useChatStore()

  // 请求控制器
  const abortController = useRef<AbortController | null>(null)
  // 历史消息
  const [messageHistory, setMessageHistory] = useState<Record<string, any>>()
  // 附件框是否打开
  const [attachmentsOpen, setAttachmentsOpen] = useState(false)
  // 附件
  const [attachedFiles, setAttachedFiles] = useState<GetProp<typeof Attachments, "items">>([])
  // 用户输入的内容
  const [inputValue, setInputValue] = useState("")

  // 用于模型调度的 Agent 钩子
  const [agent] = useXAgent<BubbleDataType>({
    // API 请求的基础 URL
    baseURL: "https://api.x.ant.design/api/llm_siliconflow_deepSeek-r1-distill-1wen-7b",
    // 模型名称
    model: "DeepSeek-R1-Distill-Qwen-7B",
    dangerouslyApiKey: "Bearer sk-xxxxxxxxxxxxxxxxxxxx"
  })
  // 请求状态
  const loading = agent.isRequesting()

  /**
   * 配合 Agent hook 进行对话数据管理
   * onRequest: 添加一条 Message，并且触发请求
   * messages: 当前管理的内容
   * setMessages: 直接修改 messages，不会触发请求
   */
  const { onRequest, messages, setMessages } = useXChat({
    agent, // 通过 useXAgent 生成的 agent，当使用 onRequest 方法时, agent 参数是必需的。
    requestFallback: (_, { error }) => {
      // 请求失败的兜底信息，不提供则不会展示
      if (error.name === "AbortError") {
        return {
          content: "Request is aborted",
          role: "assistant"
        }
      }
      return {
        content: "Request failed, please try again!",
        role: "assistant"
      }
    },
    transformMessage: (info) => {
      // 解构获取原始消息和流式数据块
      const { originMessage, chunk } = info || {}
      // 当前内容片段
      let currentContent = ""
      // 当前思考内容片段
      let currentThink = ""

      try {
        // 处理流式数据块
        if (chunk?.data && !chunk?.data.includes("DONE")) {
          // 解析JSON格式的流数据
          const message = JSON.parse(chunk?.data)
          // 获取AI的思考内容(如果有)
          currentThink = message?.choices?.[0]?.delta?.reasoning_content || ""
          // 获取AI的回复内容(如果有)
          currentContent = message?.choices?.[0]?.delta?.content || ""
        }
      } catch (error) {
        console.error(error)
      }

      // 最终组合的内容
      let content = ""

      // 逻辑处理三种情况：
      if (!originMessage?.content && currentThink) {
        // 1. 初始思考内容(没有原始消息内容但有思考内容)
        content = `<think>${currentThink}`
      } else if (
        originMessage?.content?.includes("<think>") &&
        !originMessage?.content.includes("</think>") &&
        currentContent
      ) {
        // 2. 思考结束并开始回复(有未闭合的think标签且有新内容)
        content = `${originMessage?.content}</think>${currentContent}`
      } else {
        // 3. 普通情况(直接拼接所有内容)
        content = `${originMessage?.content || ""}${currentThink}${currentContent}`
      }

      // 返回处理后的消息对象
      return {
        content: content,
        role: "assistant" // 固定为助手角色
      }
    },
    resolveAbortController: (controller) => {
      // AbortController 控制器，用于控制流状态
      abortController.current = controller
    }
  })

  /**
   * 提交用户输入的内容
   *
   * @param val 用户输入的内容
   */
  const onSubmit = (val: string) => {
    if (!val) return

    if (loading) {
      message.error("Request is in progress, please wait for the request to complete.")
      return
    }

    // 添加一条消息，并且触发请求
    onRequest({
      stream: true,
      message: { role: "user", content: val }
    })
  }

  useEffect(() => {
    // 消息列表发生变化时，更新历史消息
    if (messages?.length) {
      setMessageHistory((prev) => ({
        ...prev,
        [curConversation]: messages
      }))
    }
  }, [messages])

  useEffect(() => {
    // 当前会话变化时，停止请求并更新消息列表
    abortController.current?.abort()
    setMessages(messageHistory?.[curConversation] || [])
  }, [curConversation])

  /**
   * 消息列表组件
   */
  const chatList = (
    <div className="chat-list">
      {messages?.length ? (
        /* 🌟 消息列表 */
        <Bubble.List
          items={messages?.map((i) => ({
            ...i.message,
            classNames: {
              content: i.status === "loading" ? "loading-message" : ""
            },
            typing: i.status === "loading" ? { step: 5, interval: 20, suffix: <>💗</> } : false
          }))}
          style={{ height: "100%", paddingInline: "calc(calc(100% - 700px) /2)" }}
          roles={{
            assistant: {
              placement: "start",
              footer: (
                <div style={{ display: "flex" }}>
                  <Button type="text" size="small" icon={<ReloadOutlined />} />
                  <Button type="text" size="small" icon={<CopyOutlined />} />
                  <Button type="text" size="small" icon={<LikeOutlined />} />
                  <Button type="text" size="small" icon={<DislikeOutlined />} />
                </div>
              ),
              loadingRender: () => <Spin size="small" />
            },
            user: { placement: "end" }
          }}
        />
      ) : (
        <Space
          direction="vertical"
          size={16}
          style={{ paddingInline: "calc(calc(100% - 700px) /2)" }}
          className="placeholder"
        >
          <Welcome
            variant="borderless"
            icon={<img src={logo} alt="logo" />}
            title="Hello, I'm XYZ"
            description="Base on XYZ, AGI product interface solution, create a better intelligent vision~"
            extra={
              <Space>
                <Button icon={<ShareAltOutlined />} />
                <Button icon={<EllipsisOutlined />} />
              </Space>
            }
          />
          <Flex gap={16}>
            <Prompts
              items={[HOT_TOPICS]}
              styles={{
                list: { height: "100%" },
                item: {
                  flex: 1,
                  backgroundImage: "linear-gradient(123deg, #e5f4ff 0%, #efe7ff 100%)",
                  borderRadius: 12,
                  border: "none"
                },
                subItem: { padding: 0, background: "transparent" }
              }}
              onItemClick={(info) => {
                onSubmit(info.data.description as string)
              }}
              className="chat-prompt"
            />

            <Prompts
              items={[DESIGN_GUIDE]}
              styles={{
                item: {
                  flex: 1,
                  backgroundImage: "linear-gradient(123deg, #e5f4ff 0%, #efe7ff 100%)",
                  borderRadius: 12,
                  border: "none"
                },
                subItem: { background: "#ffffffa6" }
              }}
              onItemClick={(info) => {
                onSubmit(info.data.description as string)
              }}
              className="chat-prompt"
            />
          </Flex>
        </Space>
      )}
    </div>
  )

  /**
   * 输入框的头部面板
   */
  const senderHeader = (
    <Sender.Header
      title="Upload File"
      open={attachmentsOpen}
      onOpenChange={setAttachmentsOpen}
      styles={{ content: { padding: 0 } }}
    >
      <Attachments
        beforeUpload={() => false}
        items={attachedFiles}
        onChange={(info) => setAttachedFiles(info.fileList)}
        placeholder={(type) =>
          type === "drop"
            ? { title: "Drop file here" }
            : {
                icon: <CloudUploadOutlined />,
                title: "Upload files",
                description: "Click or drag files to this area to upload"
              }
        }
      />
    </Sender.Header>
  )

  /**
   * 对话输入框
   */
  const chatSender = (
    <>
      {/* 🌟 提示词 */}
      <Prompts
        items={SENDER_PROMPTS}
        onItemClick={(info) => {
          onSubmit(info.data.description as string)
        }}
        styles={{
          item: { padding: "6px 12px" }
        }}
        className="sender-prompt"
      />
      {/* 🌟 输入框 */}
      <Sender
        value={inputValue}
        header={senderHeader}
        onSubmit={() => {
          onSubmit(inputValue)
          setInputValue("")
        }}
        onChange={setInputValue}
        onCancel={() => {
          abortController.current?.abort()
        }}
        prefix={
          <Button
            type="text"
            icon={<PaperClipOutlined style={{ fontSize: 18 }} />}
            onClick={() => setAttachmentsOpen(!attachmentsOpen)}
          />
        }
        loading={loading}
        className="sender"
        allowSpeech
        actions={(_, info) => {
          const { SendButton, LoadingButton, SpeechButton } = info.components
          return (
            <Flex gap={4}>
              <SpeechButton className="speech-button" />
              {loading ? <LoadingButton type="default" /> : <SendButton type="primary" />}
            </Flex>
          )
        }}
        placeholder="Ask or input / use skills"
      />
    </>
  )

  return (
    <div className="chat-page">
      <div className="chat-area">
        {chatList}
        {chatSender}
      </div>
    </div>
  )
}

export default ChatPage
